package com.clear.honghefinance.biz.modules.system.role.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.clear.honghefinance.biz.modules.system.role.domain.entity.SysRoleBindResource;
import com.clear.honghefinance.biz.modules.system.member.domain.vo.AdminDTO;
import com.clear.honghefinance.biz.modules.system.role.domain.dto.RoleBindResourceDTO;
import com.clear.honghefinance.biz.modules.system.role.mapper.SysRoleBindResourceMapper;
import com.clear.honghefinance.biz.modules.system.role.service.ISysRoleBindResourceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clear.honghefinance.common.exception.BizException;
import com.clear.honghefinance.common.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色绑定资源资源 服务实现类
 * </p>
 *
 * @author 程序员clear
 * @since 2024-08-16
 */
@Service
@Slf4j
public class SysRoleBindResourceServiceImpl extends ServiceImpl<SysRoleBindResourceMapper, SysRoleBindResource> implements ISysRoleBindResourceService {

    @Resource
    private TokenService<AdminDTO> tokenService;
    @Resource
    private TransactionTemplate transactionTemplate;


    /**
     * 角色绑定资源
     *
     * @param dto req
     * @return
     */
    @Override
    public boolean roleBindResource(RoleBindResourceDTO dto) {
        // 只要传入的bindMenuIds、unBindMenuIds都会为空，就认为无需更改。具体的复选框状态由前端处理
        if (CollectionUtils.isNotEmpty(dto.getBindResourceIds()) && CollectionUtils.isNotEmpty(dto.getUnBindResourceIds())) {
            throw new BizException("您未做任何更改，不能提交绑定");
        }
        List<SysRoleBindResource> sysRoleBindResourceList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(dto.getBindResourceIds())) {
            // 1.检测角色是否已经绑定过资源
            checkRoleBindResourceIds(dto.getRoleId(), dto.getBindResourceIds());
            // 2.遍历资源id列表，封装成实体类
            for (Integer resourceId : dto.getBindResourceIds()) {
                SysRoleBindResource sysRoleBindResource = new SysRoleBindResource();
                sysRoleBindResource.setSysRoleId(dto.getRoleId());
                sysRoleBindResource.setSysResourceId(resourceId);
                sysRoleBindResource.setMemberId(tokenService.getThreadLocalUserId());
                sysRoleBindResource.setUpdateMemberId(tokenService.getThreadLocalUserId());
                sysRoleBindResource.initDefault();

                sysRoleBindResourceList.add(sysRoleBindResource);
            }
        }

        // 3.编程式事务，批量插入
        transactionTemplate.execute((transactionStatus) -> {
            // 角色绑定资源
            if (CollectionUtils.isNotEmpty(dto.getBindResourceIds())) {
                return this.saveBatch(sysRoleBindResourceList);
            }
            // 角色取消绑定资源
            if (CollectionUtils.isNotEmpty(dto.getUnBindResourceIds())) {
                LambdaUpdateWrapper<SysRoleBindResource> lambdaUpdateWrapper = Wrappers.<SysRoleBindResource>lambdaUpdate()
                        .eq(SysRoleBindResource::getSysRoleId, dto.getRoleId())
                        .eq(SysRoleBindResource::getDelFlag, false)
                        .in(SysRoleBindResource::getSysResourceId, dto.getUnBindResourceIds())
                        // 逻辑删除：即角色取消绑定资源
                        .set(SysRoleBindResource::getDelFlag, true);

                boolean updateRows = this.update(null, lambdaUpdateWrapper);
                if (!updateRows) {
                    throw new BizException("解绑失败");
                }
            }
            return true;
        });
        return true;
    }

    /**
     * 查看角色绑定的资源id列表
     *
     * @param roleId 角色id
     * @return 资源id列表
     */
    @Override
    public List<Integer> listBindResourceIdByRoleId(int roleId) {
        LambdaQueryWrapper<SysRoleBindResource> lambdaQueryWrapper = Wrappers.<SysRoleBindResource>lambdaQuery()
                .select(SysRoleBindResource::getSysResourceId)
                .eq(SysRoleBindResource::getSysRoleId, roleId)
                .eq(SysRoleBindResource::getDelFlag, false);
        List<SysRoleBindResource> roleBindResourceList = this.list(lambdaQueryWrapper);

        if (CollectionUtils.isNotEmpty(roleBindResourceList)) {
            return roleBindResourceList.stream().map(SysRoleBindResource::getSysResourceId).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 检测角色是否已经绑定过资源
     *
     * @param roleId      角色id
     * @param resourceIds 资源id列表
     */

    private void checkRoleBindResourceIds(Integer roleId, List<Integer> resourceIds) {
        LambdaQueryWrapper<SysRoleBindResource> lambdaQueryWrapper = Wrappers.<SysRoleBindResource>lambdaQuery()
                .eq(SysRoleBindResource::getSysRoleId, roleId)
                .in(SysRoleBindResource::getSysResourceId, resourceIds)
                .eq(SysRoleBindResource::getDelFlag, false);
        int count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            throw new BizException("角色不要重复绑定资源");
        }
    }
}
